
#include "member_BScene.h"
#include "member_BGroup.h"
#include "member_BShape.h"
#include "member_BNode.h"
#include "member_BCamera.h"

using namespace BWE;

member_BScene::member_BScene(BScene* scene)
{
	boss = scene;
	refresh = false;
	dirtySpace = false;
}
member_BScene::~member_BScene()
{

}

void member_BScene::update(BReal time)
{
	for (int i = 0; i < shapes.size(); i++)
	{
		BShape* shape = shapes[i];
		if (shape_member(shape)->dirty)
		{
			shape->flush();
		}
	}
	for (int i = 0; i < nodes.size(); i++)
	{
		BNode* node = nodes[i];
		BShapeHolderArray& shapes = node_member(node)->shapes;
		for (int i = 0; i < shapes.size(); i++)
		{
			BShape* shape = shapes[i];
			if (shape_member(shape)->dirty)
			{
				shape->flush();
				node_member(node)->dirtyBox = true;
				node_member(node)->dirtySpace = true;
			}
		}
		if (node_member(node)->dirtySpace)
		{
			node->space();
		}
	}
	for (int i = 0; i < groups.size(); i++)
	{
		BGroup* group = groups[i];
		updateGroup(group, time);
	}
	if (dirtySpace)
	{
		boss->space();
	}
	if (refresh)
	{
		for (int i = 0; i < cameras.size(); i++)
		{
			BCamera* camera = cameras[i];
			camera_member(camera)->refresh = true;
		}
		boss->emit(Signal_Fresh);
		refresh = false;
	}
	boss->update(time);
}
void member_BScene::updateGroup(BGroup* group, BReal time)
{
	for (int i = 0; i < group->shapeCount(); i++)
	{
		BShape* shape = group->shape(i);
		if (shape_member(shape)->dirty)
		{
			shape->flush();
		}
	}
	for (int i = 0; i < group->nodeCount(); i++)
	{
		BNode* node = group->node(i);
		BShapeHolderArray& shapes = node_member(node)->shapes;
		for (int i = 0; i < shapes.size(); i++)
		{
			BShape* shape = shapes[i];
			if (shape_member(shape)->dirty)
			{
				shape->flush();
				node_member(node)->dirtyBox = true;
				node_member(node)->dirtySpace = true;
			}
		}
		if (node_member(node)->dirtySpace)
		{
			node->space();
		}
	}
	for (int i = 0; i < group->childCount(); i++)
	{
		BGroup* child = group->child(i);
		updateGroup(child, time);
	}
	if (group->enabled())
	{
		group_member(group)->update(time);
	}
}

void member_BScene::freshOctTree()
{
	BSpace octSpace = sceneOctTree->space();
	const BSpace& space = boss->space();
	if (sceneOctTree->empty() || !octSpace.contain(space))
	{
		sceneOctTree->reset(space * 2.0f);
		shapeSpaceMap.reserve(shapes.size());
		nodeSpaceMap.reserve(nodes.size());
		for (int i = 0; i < shapes.size(); i++)
		{
			BShape* shape = shapes[i];
			SceneOctTreeItem item = sceneOctTree->create(shape->space());
			item->shapes.append(shape);
			shapeSpaceMap[shape] = item;
		}
		for (int i = 0; i < nodes.size(); i++)
		{
			BNode* node = nodes[i];
			SceneOctTreeItem item = sceneOctTree->create(node->space());
			item->nodes.append(node);
			nodeSpaceMap[node] = item;
		}
		for (int i = 0; i < groups.size(); i++)
		{
			BGroup* group = groups[i];
			freshGroupOctTree(group);
		}
	}
}
void member_BScene::freshGroupOctTree(BGroup* group)
{
	for (int i = 0; i < group->shapeCount(); i++)
	{
		BShape* shape = group->shape(i);
		SceneOctTreeItem item = sceneOctTree->create(shape->space());
		item->shapes.append(shape);
		shapeSpaceMap[shape] = item;
	}
	for (int i = 0; i < group->nodeCount(); i++)
	{
		BNode* node = group->node(i);
		SceneOctTreeItem item = sceneOctTree->create(node->space());
		item->nodes.append(node);
		nodeSpaceMap[node] = item;
	}
	for (int i = 0; i < group->childCount(); i++)
	{
		BGroup* child = group->child(i);
		freshGroupOctTree(child);
	}
}

void member_BScene::collectShapes(SceneOctTreeItem& item, BShapeArray& shapes)
{
	shapes.append(item->shapes);
	for (int i = 0; i < 8; i++)
	{
		SceneOctTreeItem lower = item.lower(i);
		if (lower.empty())
			continue;
		collectShapes(lower, shapes);
	}
}
void member_BScene::collectNodes(SceneOctTreeItem& item, BNodeArray& nodes)
{
	nodes.append(item->nodes);
	for (int i = 0; i < 8; i++)
	{
		SceneOctTreeItem lower = item.lower(i);
		if (lower.empty())
			continue;
		collectNodes(lower, nodes);
	}
}
void member_BScene::collectLights(SceneOctTreeItem& item, BLightArray& lights)
{
	lights.append(item->lights);
	for (int i = 0; i < 8; i++)
	{
		SceneOctTreeItem lower = item.lower(i);
		if (lower.empty())
			continue;
		collectLights(lower, lights);
	}
}
void member_BScene::collectCameras(SceneOctTreeItem& item, BCameraArray& cameras)
{
	cameras.append(item->cameras);
	for (int i = 0; i < 8; i++)
	{
		SceneOctTreeItem lower = item.lower(i);
		if (lower.empty())
			continue;
		collectCameras(lower, cameras);
	}
}

void member_BScene::slotShapeEnabled(BObject* object)
{
	BShape* shape = (BShape*)object;
	if (shape_member(shape)->visible)
		refresh = true;
}
void member_BScene::slotShapeFresh(BObject* object)
{
	BShape* shape = (BShape*)object;
	if (shape_member(shape)->visible)
		refresh = true;
}
void member_BScene::slotShapeDirty(BObject* object)
{
	BShape* shape = (BShape*)object;
	if (shape_member(shape)->visible)
		refresh = true;
	dirtySpace = true;
	boss->emit(Signal_Dirty, object);
}
void member_BScene::slotShapeTransformed(BObject* object)
{
	BShape* shape = (BShape*)object;
	if (shape_member(shape)->visible)
		refresh = true;
	if (!space.contain(shape->space()))
	{
		dirtySpace = true;
	}
	if (sceneOctTree)
	{
		SceneOctTreeItem& olditem = shapeSpaceMap[shape];
		olditem->shapes.remove(shape);

		SceneOctTreeItem item = sceneOctTree->create(shape->space());
		item->shapes.append(shape);
		shapeSpaceMap[shape] = item;
	}
	boss->emit(Signal_Dirty, object);
}

void member_BScene::slotNodeEnabled(BObject* object)
{
	refresh = true;
}
void member_BScene::slotNodeFresh(BObject* object)
{
	refresh = true;
}
void member_BScene::slotNodeDirty(BObject* object)
{
	refresh = true;
	dirtySpace = true;
	boss->emit(Signal_Dirty, object);
}
void member_BScene::slotNodeInsert(BObject* object, const BValue& value)
{
	boss->emit(Signal_Insert, value);
}
void member_BScene::slotNodeRemove(BObject* object, const BValue& value)
{
	boss->emit(Signal_Remove, value);
}
void member_BScene::slotNodeTransformed(BObject* object)
{
	BNode* node = (BNode*)object;
	if (node_member(node)->visible)
		refresh = true;
	if (!space.contain(node->space()))
	{
		dirtySpace = true;
		return;
	}
	if (sceneOctTree)
	{
		SceneOctTreeItem& olditem = nodeSpaceMap[node];
		olditem->nodes.remove(node);

		SceneOctTreeItem item = sceneOctTree->create(node->space());
		item->nodes.append(node);
		nodeSpaceMap[node] = item;
	}
	boss->emit(Signal_Dirty, object);
}

void member_BScene::slotGroupEnabled(BObject* object)
{
	refresh = true;
}
void member_BScene::slotGroupFresh(BObject* object)
{
	refresh = true;
	dirtySpace = true;
}
void member_BScene::slotGroupDirty(BObject* object)
{
	refresh = true;
	dirtySpace = true;
	boss->emit(Signal_Dirty, object);
}
void member_BScene::slotGroupInsert(BObject* object, const BValue& value)
{
	boss->emit(Signal_Insert, value);
}
void member_BScene::slotGroupRemove(BObject* object, const BValue& value)
{
	boss->emit(Signal_Remove, value);
}

